/*
 * Copyright (C) 2011 Andreas Petersson
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package at.petersson.interner;

import at.petersson.interner.wrappers.*;

import java.util.IdentityHashMap;
import java.util.List;

/**
 * @author apetersson
 *         this class exists because arrays do not implement hashCode() and equals() as desired
 */
class Wrappers {

    static Object replaceWithWrapper(Object newObject, DeepInterner deepInterner, IdentityHashMap<Object, List<Notifier>> workList) throws IllegalAccessException {
        if (newObject instanceof boolean[]) {
            return new BooleanArrayWrapper((boolean[]) newObject);
        } else if (newObject instanceof byte[]) {
            return new ByteArrayWrapper((byte[]) newObject);
        } else if (newObject instanceof char[]) {
            return new CharArrayWrapper((char[]) newObject);
        } else if (newObject instanceof double[]) {
            return new DoubleArrayWrapper((double[]) newObject);
        } else if (newObject instanceof float[]) {
            return new FloatArrayWrapper((float[]) newObject);
        } else if (newObject instanceof int[]) {
            return new IntArrayWrapper((int[]) newObject);
        } else if (newObject instanceof long[]) {
            return new LongArrayWrapper((long[]) newObject);
        } else if (newObject instanceof short[]) {
            return new ShortArrayWrapper((short[]) newObject);
        } else if (newObject instanceof Object[]) {
            final Object[] rawArray = (Object[]) newObject;
            newObject = new ObjectArrayWrapper(rawArray);
            for (int i = 0; i < rawArray.length; i++) {
                Object fieldValue = rawArray[i];
                final List<Notifier> runnable = workList.get(fieldValue);
                if (runnable == null) {
                    if (fieldValue != null) {
                        rawArray[i] = deepInterner.intern2(fieldValue, workList);
                    }
                } else { //do not recurse, it is already being worked on... instead notify me as soon as a result is available
                    final int currentIndex = i;
                    runnable.add(new Notifier() {
                        @Override
                        public void run(Object freshlyInterned) throws IllegalAccessException {
                            rawArray[currentIndex] = freshlyInterned;
                        }
                    });
                }
            }
            return newObject;
        } else {
            throw new UnsupportedOperationException("converter for arrays of type: " + newObject.getClass() + " not yet implemented..");
        }
    }

}
